/**
 ******************************************************************************
 * @file           : bsp_memory_config.c
 * @brief          : BSP Memory Management Implementation
 ******************************************************************************
 */

/* Includes ------------------------------------------------------------------*/
#include "bsp_memory_config.h"
#include <string.h>

/* Private types -------------------------------------------------------------*/

#if (BSP_MEMORY_POOL_ENABLE == 1)

/**
 * @brief 内存块结构体
 */
typedef struct MemBlock
{
    struct MemBlock *next;      /*!< 下一个空闲块 */
    uint8_t used;               /*!< 是否已使用 */
} MemBlock_t;

/**
 * @brief 内存池结构体
 */
typedef struct
{
    uint8_t pool[BSP_MEMORY_POOL_SIZE];     /*!< 内存池 */
    MemBlock_t *free_list;                  /*!< 空闲链表 */
    uint32_t total_blocks;                  /*!< 总块数 */
    uint32_t used_blocks;                   /*!< 已使用块数 */
} MemPool_t;

#endif

/* Private variables ---------------------------------------------------------*/

#if (BSP_MEMORY_POOL_ENABLE == 1)
static MemPool_t sg_mem_pool;
#endif

#if (BSP_MEMORY_STATS_ENABLE == 1)
static uint32_t sg_total_alloc = 0;     /*!< 总分配字节数 */
static uint32_t sg_total_free = 0;      /*!< 总释放字节数 */
static uint32_t sg_peak_usage = 0;      /*!< 峰值使用 */
static uint32_t sg_current_usage = 0;   /*!< 当前使用 */
#endif

/* Private function prototypes -----------------------------------------------*/
/* Exported functions --------------------------------------------------------*/

#if (BSP_MEMORY_POOL_ENABLE == 1)

/**
 * @brief       初始化内存池
 */
void mem_pool_init(void)
{
    uint32_t i;
    MemBlock_t *block;
    
    /* 清空内存池 */
    memset(&sg_mem_pool, 0, sizeof(MemPool_t));
    
    /* 初始化空闲链表 */
    sg_mem_pool.total_blocks = BSP_MEMORY_BLOCK_NUM;
    sg_mem_pool.used_blocks = 0;
    
    for (i = 0; i < sg_mem_pool.total_blocks; i++)
    {
        block = (MemBlock_t *)&sg_mem_pool.pool[i * BSP_MEMORY_BLOCK_SIZE];
        block->used = 0;
        block->next = (i == sg_mem_pool.total_blocks - 1) ? NULL : 
                      (MemBlock_t *)&sg_mem_pool.pool[(i + 1) * BSP_MEMORY_BLOCK_SIZE];
    }
    
    sg_mem_pool.free_list = (MemBlock_t *)sg_mem_pool.pool;
}

/**
 * @brief       从内存池分配内存
 *
 * @param[in]   size: 请求的字节数
 *
 * @retval      内存指针，失败返回NULL
 */
void* mem_pool_alloc(size_t size)
{
    MemBlock_t *block;
    
    if (size == 0 || size > BSP_MEMORY_BLOCK_SIZE || sg_mem_pool.free_list == NULL)
    {
        return NULL;
    }
    
    /* 从空闲链表取出一个块 */
    block = sg_mem_pool.free_list;
    sg_mem_pool.free_list = block->next;
    
    block->used = 1;
    block->next = NULL;
    sg_mem_pool.used_blocks++;
    
#if (BSP_MEMORY_STATS_ENABLE == 1)
    sg_total_alloc += BSP_MEMORY_BLOCK_SIZE;
    sg_current_usage += BSP_MEMORY_BLOCK_SIZE;
    if (sg_current_usage > sg_peak_usage)
    {
        sg_peak_usage = sg_current_usage;
    }
#endif
    
    /* 返回数据区（跳过块头） */
    return (void *)((uint8_t *)block + sizeof(MemBlock_t));
}

/**
 * @brief       释放内存到内存池
 *
 * @param[in]   ptr: 内存指针
 */
void mem_pool_free(void *ptr)
{
    MemBlock_t *block;
    
    if (ptr == NULL)
    {
        return;
    }
    
    /* 获取块头 */
    block = (MemBlock_t *)((uint8_t *)ptr - sizeof(MemBlock_t));
    
#if (BSP_MEMORY_DOUBLE_FREE_CHECK == 1)
    if (block->used == 0)
    {
        log_e("Double free detected!");
        return;
    }
#endif
    
    /* 放回空闲链表 */
    block->used = 0;
    block->next = sg_mem_pool.free_list;
    sg_mem_pool.free_list = block;
    sg_mem_pool.used_blocks--;
    
#if (BSP_MEMORY_STATS_ENABLE == 1)
    sg_total_free += BSP_MEMORY_BLOCK_SIZE;
    sg_current_usage -= BSP_MEMORY_BLOCK_SIZE;
#endif
}

/**
 * @brief       获取内存池使用情况
 *
 * @param[out]  total: 总容量
 * @param[out]  used: 已使用
 * @param[out]  free: 剩余空间
 */
void mem_pool_get_info(uint32_t *total, uint32_t *used, uint32_t *free)
{
    if (total) *total = sg_mem_pool.total_blocks * BSP_MEMORY_BLOCK_SIZE;
    if (used)  *used = sg_mem_pool.used_blocks * BSP_MEMORY_BLOCK_SIZE;
    if (free)  *free = (sg_mem_pool.total_blocks - sg_mem_pool.used_blocks) * BSP_MEMORY_BLOCK_SIZE;
}

#endif /* BSP_MEMORY_POOL_ENABLE */

/*============================================================================*/
/*                           内存统计函数                                      */
/*============================================================================*/

#if (BSP_MEMORY_STATS_ENABLE == 1)

/**
 * @brief       获取内存使用统计
 *
 * @param[out]  total_alloc: 总分配字节数
 * @param[out]  total_free: 总释放字节数
 * @param[out]  peak_usage: 峰值使用
 */
void mem_get_stats(uint32_t *total_alloc, uint32_t *total_free, uint32_t *peak_usage)
{
    if (total_alloc) *total_alloc = sg_total_alloc;
    if (total_free)  *total_free = sg_total_free;
    if (peak_usage)  *peak_usage = sg_peak_usage;
}

/**
 * @brief       打印内存使用情况
 */
void mem_print_stats(void)
{
    printf("\r\n");
    printf("========================================\r\n");
    printf("  Memory Statistics\r\n");
    printf("========================================\r\n");
    printf("Total Allocated: %lu bytes\r\n", sg_total_alloc);
    printf("Total Freed:     %lu bytes\r\n", sg_total_free);
    printf("Current Usage:   %lu bytes\r\n", sg_current_usage);
    printf("Peak Usage:      %lu bytes\r\n", sg_peak_usage);
    printf("========================================\r\n");
    printf("\r\n");
}

/**
 * @brief       重置内存统计
 */
void mem_reset_stats(void)
{
    sg_total_alloc = 0;
    sg_total_free = 0;
    sg_peak_usage = 0;
    sg_current_usage = 0;
}

#endif /* BSP_MEMORY_STATS_ENABLE */

/*============================================================================*/
/*                           FreeRTOS兼容函数                                  */
/*============================================================================*/

#if (BSP_MEMORY_TYPE == 1)

/**
 * @brief       calloc实现（FreeRTOS没有提供）
 */
void* bsp_calloc(size_t num, size_t size)
{
    size_t total = num * size;
    void *ptr = BSP_MALLOC(total);
    
    if (ptr != NULL)
    {
        memset(ptr, 0, total);
    }
    
    return ptr;
}

/**
 * @brief       realloc实现（FreeRTOS没有提供）
 */
void* bsp_realloc(void *ptr, size_t size)
{
    void *new_ptr;
    
    if (ptr == NULL)
    {
        return BSP_MALLOC(size);
    }
    
    if (size == 0)
    {
        BSP_FREE(ptr);
        return NULL;
    }
    
    new_ptr = BSP_MALLOC(size);
    if (new_ptr != NULL)
    {
        /* 注意：这里无法知道原内存大小，可能导致问题 */
        memcpy(new_ptr, ptr, size);
        BSP_FREE(ptr);
    }
    
    return new_ptr;
}

#endif /* BSP_MEMORY_TYPE == 1 */
